package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.heima.common.constants.message.PublishArticleConstants;
import com.heima.aliyun.GreenImageScan;
import com.heima.aliyun.GreenTextScan;
import com.heima.common.exception.CustomException;
import com.heima.feigns.AdminFeign;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WmNewsAutoScanWmNewsImpl implements WmNewsAutoScanService {
    @Autowired
    AdminFeign adminFeign;
    @Autowired
    WmNewsMapper wmNewsMapper;
    @Autowired
    RabbitTemplate rabbitTemplate;

    /**
     *      文章 审核
     * @param id  自媒体文章id
     */
    @Override
    public void autoScanWmNews(Integer id) {
        // 参数校验
        if (id == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 根据id 获取文章数据
        WmNews wmNews = wmNewsMapper.selectById(id);
        // 判断文章是否为空
        if (wmNews == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // 检查文章是否为待审核
        if (wmNews.getStatus() != 1) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_ALLOW,"文章不是待审核阶段");
        }

        // 敏感检验   获取文本集  content 和  图片集       images
        Map<String,Object> textAndImages = findAllTextAndImages(wmNews);

        //   1.   DFA 审核
        Boolean DFAResult =handleSensitive((String)textAndImages.get("content"),wmNews);
        if (!DFAResult) {//  审核 结束 直接返回
            return;
        }
        log.info("敏感词审核结束================");

        //   阿里云  文本审核
        Boolean textScanResult = handleTextScan((String) textAndImages.get("content"), wmNews);
        if (!textScanResult) {
            return;
        }
        log.info("阿里云文本审核结束===========");

        //   阿里云  图片审核
        Object images = textAndImages.get("images");

        Boolean inagesScanResult = handleImagesScan((List<String>)images,wmNews);
        if (!inagesScanResult) {
            return;
        }
        log.info("阿里云图片审核结束===========");

        //  修改状态
        updateWmNews(wmNews,(short) 8,"通过");
        //5. 通知定时发布文章
        // 发布时间
        long publishTime = wmNews.getPublishTime().getTime();
        // 当前时间
        long nowTime = System.currentTimeMillis();
        //延时时间
        long delayTime = publishTime-nowTime<=0?0:publishTime-nowTime;
        // 发布文章
        rabbitTemplate.convertAndSend(PublishArticleConstants.DELAY_DIRECT_EXCHANGE
                , PublishArticleConstants.PUBLISH_ARTICLE_ROUTE_KEY
                , wmNews.getId()
                , new MessagePostProcessor() {
                    @Override
                    public Message postProcessMessage(Message message) throws AmqpException {
                        message.getMessageProperties().setHeader("x-delay",delayTime);
                        return message;
                    }
                });

        log.info("立即发布文章通知成功发送，文章id : {}", wmNews.getId());




    }
    @Autowired
    GreenImageScan greenImageScan;
    /**
     *      阿里云图片审核
     * @param images
     * @param wmNews
     * @return
     */
    private Boolean handleImagesScan(List<String> images, WmNews wmNews) {
        boolean flag = true;
        try {
            Map map = greenImageScan.imageUrlScan(images);
            String suggestion = (String)map.get("suggestion");
            switch (suggestion){
                case "block": //  内容违规    失败
                    updateWmNews(wmNews,(short)2,"内容违规");
                    flag = false;
                    break;
                case "review"://  内容不确定   需要人工
                    updateWmNews(wmNews,(short)3,"需要人工");
                    flag = false;
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("阿里云图片审核过程出错，原因：{}",e.getMessage());
            updateWmNews(wmNews,(short)3,"需要人工");
            flag = false;
        }
        return flag;

    }

    @Autowired
    GreenTextScan greenTextScan;
    /**
     *      阿里云 文本检测
     * @param content
     * @param wmNews
     * @return
     */
    private Boolean handleTextScan(String content, WmNews wmNews) {
        boolean flag = true;
        try {
            Map map = greenTextScan.greenTextScan(content);
            String suggestion = (String)map.get("suggestion");
            switch (suggestion){
                case "block": //  内容违规    失败
                    updateWmNews(wmNews,(short)2,"内容违规");
                    flag = false;
                    break;
                case "review"://  内容不确定   需要人工
                    updateWmNews(wmNews,(short)3,"需要人工");
                    flag = false;
                    break;
            }
            
        } catch (Exception e) {
            e.printStackTrace();
            log.error("阿里云文本审核过程出错，原因：{}",e.getMessage());
            updateWmNews(wmNews,(short)3,"需要人工");
            flag = false;
        }
        return flag;

    }

    /**
     *    ，敏感词校验    返回 true  false    并改变wnnews 的审核状态
     * @param content
     * @param wmNews
     * @return
     */
    private Boolean handleSensitive(String content, WmNews wmNews) {
        Boolean flag = true;
        //  1.  获取本地敏感词
        ResponseResult<List<String>> getSensitivesResult = adminFeign.findAllSensitive();
        if (getSensitivesResult.getCode().intValue() != 0) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST,"获取敏感词失败");
        }
        List<String> allSensitives = getSensitivesResult.getData();
        //  2. 将敏感词转发到DFA模型中
        SensitiveWordUtil.initMap(allSensitives);
        //  3. 检测敏感词
        Map<String, Integer> resultMap = SensitiveWordUtil.matchWords(content);
        if (resultMap != null && resultMap.size() > 0) {
            //4. 审核结果  失败  将状态设置为未通过 2
            updateWmNews(wmNews,(short) 2,"包含敏感词"+resultMap.toString() );
            flag = false;
        }
        return flag;


    }

    /**
     *        更改wmnews的状态
     * @param wmNews
     * @param status
     * @param reason
     * status字段：0 草稿  1 待审核  2 审核失败  3 人工审核  4 人工审核通过  8 审核通过（待发布） 9 已发布
     */
    private void updateWmNews(WmNews wmNews, short status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wmNewsMapper.updateById(wmNews);
    }

    @Value("${file.oss.web-site}")
    String webSite;
    /**
     * 抽取文章中所有的  文本 和图片
     *
     * @param wmNews
     * @return
     */
    private Map<String, Object> findAllTextAndImages(WmNews wmNews) {
        HashMap<String, Object> result = new HashMap<>();

        String contentJson = wmNews.getContent();
        List<Map> contentMap = JSONArray.parseArray(contentJson, Map.class);
        //  获取文本内容
        StringBuilder contentText = new StringBuilder(wmNews.getTitle());
        contentMap.stream()
                .filter(map -> "text".equals(map.get("type")))  //  过滤 map的类型为text的
                .map(o ->(String)o.get("value") )              //   获取value 的 值
                .forEach((text)->contentText.append("--"+text)  );  //  遍历写入  StringBuild
        result.put("content",contentText.toString());
        //  获取图片内容
        //  获取内容中的图片
        List<String> imagesList = contentMap.stream()
                .filter(map -> "image".equals(map.get("type")))  //  过滤 map的类型为text的
                .map(o -> (String) o.get("value"))              //   获取value 的 值
                .collect(Collectors.toList());
        //  获取  封面中的图片
        if (StringUtils.isBlank(wmNews.getImages())) {  //  参数检测
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //  将 封面的字符串 用 ‘，’ 分割为数组用stream 流  生成集合
        List<String> imagesList2 = Arrays.stream(wmNews.getImages().split(","))
                .map(url -> webSite + url).collect(Collectors.toList());
        imagesList.addAll(imagesList2);
        //  去重
        List<String> list = imagesList.stream().distinct().collect(Collectors.toList());
        result.put("images",list);

        return result ;
    }
}
